#ifndef CONTEXT_H
#define CONTEXT_H

#include <QThread>
#include <QWaitCondition>
#include <QReadWriteLock>
#include "scene.h"
#include "junction.h"
#include "way.h"
#include "datacache.h"
#include "touchitem.h"
#include "mappixmapitem.h"

class Context : public QThread
{
    Q_OBJECT
public:
    class Options
    {
    public:
        QSize viewPortSize;
        double cachePercent;
        Point viewCenter;
        double viewPercent;  // 0...1,0 - from point to entire Earth
        qreal angle;
        qreal scale;
        quint32 mapDetalization;
        bool antialising;
    };
private:
    DataCache dataCache;
    Options options;
    Options lastOptions;
    QQueue<Options> optionsQueue;
    Scene * mapScene;
    QSharedPointer<QImage> imagePtr;
    MapPixmapItem * pixmapItem;
    QPixmap minePixmap;
    TouchItem * zoomInItem;
    TouchItem * zoomOutItem;
    TouchItem * rotateClockwiseItem;
    TouchItem * rotateAnticlockwiseItem;
    QMap<quint64, Junction *> junctions;
    QMap<quint64, Way *> ways;
    bool doStop;
    QWaitCondition paintWait;
    mutable QReadWriteLock rwLock;

    void initTestMap();
protected:
    void run();
public:
    explicit Context(const Point & center, const QSize & displaySize, QObject *parent = 0);
    ~Context();
    Scene * scene() const;
    const Point & center() const;
    double cacheRadius() const;
    const Options & getOptions() const;
    bool isAntialiased() const;
    void move(double dlatitude, double dlongitude);
    void moveTo(double latitude, double longitude);
private:
    void stop();
    static int x0(const Point & p, const Point & center, qreal scale, qreal angle);
    static int y0(const Point & p, const Point & center, qreal scale, qreal angle);
    static int x(const Point & p, const Point & center, qreal scale, qreal angle, short viewPortWidth, short xshift = 0);
    static int y(const Point & p, const Point & center, qreal scale, qreal angle, short viewPortHeight, short yshift = 0);
    void updateScale();
    void updateCache();
    void draw();
    void repaint();
    bool isFlat() const;
    bool needRepaint();
    static void drawGrid(QPaintDevice * paintDevice, const Options & drawOptions);
    void createTouchMenu();
    void arrangeTouchMenu();

signals:
    void imageReady();

public slots:
    void resize(const QSize & size);
    void updateScene();
    void handleMove(qreal dx, qreal dy);
    void handleZoom(qreal dscale, const QPointF & constPoint);
    void zoomIn();
    void zoomOut();
    void rotateClockwise();
    void rotateAnticlockwise();
    void updateAntialiasing(int checkBoxState);
    void updateBuildingShow(int checkBoxState);
    void updateWayShow(int checkBoxState);
};

#endif // CONTEXT_H
